package yagwl.service.fnd.security;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import yagwl.service.fnd.security.AccessControlEntity.Role;
import yagwl.service.util.db.DaoContext;
import yagwl.service.util.svc.BaseException;
import yagwl.service.util.svc.BaseException.ErrorCode;

public class AccessControlDao {

  private static final Logger log = Logger.getLogger(AccessControlDao.class
      .getName());

  private DaoContext ctx;

  public AccessControlDao(DaoContext ctx) {
    this.ctx = ctx;
  }

  public AccessControlEntity create(AccessControlEntity dac) {
    EntityManager em = ctx.em();
    try {
      em.getTransaction().begin();
      em.persist(dac);
      em.getTransaction().commit();
    } catch (Exception e) {
      log.severe(e.toString());
      em.getTransaction().rollback();
      throw new BaseException(ErrorCode.INTERNAL_TRANSACTION_ERROR, e);
    }
    return dac;
  }

  public void delete(AccessControlEntity dac) {
    EntityManager em = ctx.em();
    try {
      em.getTransaction().begin();
      // some hack to make things work (forcing attach)
      AccessControlEntity dac2 = em.find(AccessControlEntity.class,
          dac.getAccessControlId());
      em.remove(dac2);
      em.getTransaction().commit();
    } catch (Exception e) {
      log.severe(e.toString());
      em.getTransaction().rollback();
      throw new BaseException(ErrorCode.INTERNAL_TRANSACTION_ERROR, e);
    }
  }

  public AccessControlEntity getUserData(String userId, String stage,
      String objectEntity, Long objectId) {
    EntityManager em = ctx.em();
    Query q = em
        .createQuery(
            "select from AccessControlEntity where userId = :userId "
                + "and stage = :stage and objectEntity = :objectEntity "
                + "and objectId = :objectId ").setParameter("userId", userId)
        .setParameter("stage", stage)
        .setParameter("objectEntity", objectEntity)
        .setParameter("objectId", objectId);
    try {
      return (AccessControlEntity) q.getSingleResult();
    } catch (NoResultException e) {
      return null;
    }
  }

  public List<AccessControlEntity> getUserData(String userId,
      String objectEntity) {
    EntityManager em = ctx.em();
    Query q = em
        .createQuery(
            "select from AccessControlEntity where userId = :userId "
                + "and objectEntity = :objectEntity")
        .setParameter("userId", userId)
        .setParameter("objectEntity", objectEntity);
    return getData(q);
  }

  public List<AccessControlEntity> getUsersForRole(Role role,
      String objectEntity, Long objectId) {
    EntityManager em = ctx.em();
    Query q = em
        .createQuery(
            "select from AccessControlEntity "
                + "where objectEntity = :objectEntity and objectId = :objectId "
                + "and role = :role")
        .setParameter("objectEntity", objectEntity)
        .setParameter("objectId", objectId).setParameter("role", role);
    return getData(q);
  }

  public List<AccessControlEntity> getUsers(String objectEntity, Long objectId) {
    EntityManager em = ctx.em();
    Query q = em
        .createQuery(
            "select from AccessControlEntity "
                + "where objectEntity = :objectEntity and objectId = :objectId ")
        .setParameter("objectEntity", objectEntity)
        .setParameter("objectId", objectId);
    return getData(q);
  }

  @SuppressWarnings("unchecked")
  private List<AccessControlEntity> getData(Query q) {
    List<AccessControlEntity> list = null;
    try {
      list = (List<AccessControlEntity>) q.getResultList();
      for (@SuppressWarnings("unused")
      AccessControlEntity wl : list)
        ;
    } catch (Exception e) {
      log.severe(e.toString());
      list = new ArrayList<AccessControlEntity>();
    }
    log.info("" + list.size());
    return list;
  }
}
